/* CS180 Project 4
 * Matthew Rodgers
 * Scott Wilkewitz
 * CSLOGIN: rodgersm and swilkewi
 */

import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;

public class Quiz implements ActionListener, MenuListener, WindowListener
{
  
  ////////////////////////////////////////// ///////////////////////////////////////
  //Members
  ////////////////////////////////////////// ///////////////////////////////////////
  
  //Quiz Frame
  JFrame quizFrame;
  JPanel answerPanel, framePanel, questionPanel;
  JButton answerA, answerB, answerC, answerD, nextButton;
  JLabel questionA, questionB, questionC, questionD, displayedQuestionLabel;
  
  //Quiz Frame Menu
  JMenuBar quizMenu;
  JMenu user, start, turnin;
  JMenuItem newUser, login, logout;
  
  //Login Frame
  Frame loginFrame;
  JTextField userTextField;
  JPasswordField passwordTextField;
  JButton okButton, cancelButton;
  
  //Quiz Data
  final int maxQuestions = 20;
  final int numAnswers = 4;
  int numQuestions = 6;
  int limit = 3;
  final int quizDataWidth = numAnswers + 2;
  String[][] quizData = new String[maxQuestions][quizDataWidth];
  
  //CurrentQuestion
  int currentQuestion = 0;
  String currentAnswer = "a";
  
  //User Data
  final int maxUser = 50;
  int numUsers = 0;
  String[][] userData =new String[maxUser][4];
  String[] answers = new String[maxQuestions];
  
  //Current User
  int currentUser = -1;
  int numQuestionsAnswered = 0;
  
  ////////////////////////////////////////// ///////////////////////////////////////
  //Initialization
  ////////////////////////////////////////// ///////////////////////////////////////
  
  public static void main(String[] args)
  {
    new Quiz();
  }
  
  public Quiz()
  {
    
    //Load Data
    loadQuestions("Questions.txt");
    loadAnswers("Sol.txt");
    loadUsers("Data.txt");
    
    //Start Quiz Program
    createMenu();
    createButtons();
    createLabels();
    createPanels();
    createFrame();
  }
  
  public void createFrame()
  {
    
    quizFrame = new JFrame("CS Quiz System");
    quizFrame.setSize(500,500);
    quizFrame.setLayout(new BorderLayout());
    
    displayedQuestionLabel = new JLabel("Login or create an account.");
    quizFrame.add(displayedQuestionLabel, BorderLayout.NORTH);
    quizFrame.add(framePanel, BorderLayout.CENTER);
    quizFrame.add(nextButton, BorderLayout.SOUTH);
    
    quizFrame.setJMenuBar(quizMenu);
    quizFrame.addWindowListener(this);
    quizFrame.setVisible(true);
  }
  
  public void createMenu()
  {
    
    quizMenu = new JMenuBar();
    
    //New User
    user = new JMenu("User");
    newUser = new JMenuItem("New User");
    newUser.addActionListener(this);
    user.add(newUser);
    
    //Login
    login = new JMenuItem("Log In");
    login.addActionListener(this);
    user.add(login);
    
    //Logout
    logout = new JMenuItem("Log Out");
    logout.addActionListener(this);
    logout.setEnabled(false);
    user.add(logout);
    
    //Start Menu
    start = new JMenu("Start");
    start.addMenuListener(this);
    start.setEnabled(false);
    
    //Turnin Menu
    turnin = new JMenu("Turnin");
    turnin.addMenuListener(this);
    turnin.setEnabled(false);
    
    quizMenu.add(user);
    quizMenu.add(start);
    quizMenu.add(turnin);
  }
  
  public void createPanels()
  {
   
    //Answer Panel
    answerPanel = new JPanel(new GridLayout(4,1));
    answerPanel.add(answerA);
    answerPanel.add(answerB);
    answerPanel.add(answerC);
    answerPanel.add(answerD);
    
    //Question Panel
    questionPanel = new JPanel(new GridLayout(4,1));
    questionPanel.add(questionA);
    questionPanel.add(questionB);
    questionPanel.add(questionC);
    questionPanel.add(questionD);
    
    //Frame Panel
    framePanel = new JPanel(new GridLayout(0,2)); 
    framePanel.add(answerPanel);
    framePanel.add(questionPanel);
  }
  
  public void createLabels()
  {
    
    questionA = new JLabel("");
    questionB = new JLabel("");
    questionC = new JLabel("");
    questionD = new JLabel("");
  }
  
  public void createButtons()
  {
    
    answerA = new JButton("A");
    answerA.addActionListener(this);
    
    answerB = new JButton("B");
    answerB.addActionListener(this);
    
    answerC = new JButton("C");
    answerC.addActionListener(this);
    
    answerD = new JButton("D");
    answerD.addActionListener(this);
    
    nextButton = new JButton("Next");
    nextButton.addActionListener(this);
    nextButton.setEnabled(false);
  }
  
  //////////////////////////////////////////
  //Data Reading
  //////////////////////////////////////////
  
  public void loadQuestions(String filename)
  {
    
    Scanner in = null;
    
    try{
      in = new Scanner(new File(filename));
    }catch(Exception e){}
    
    //Load Data for each Question
    for(int r = 0; r < numQuestions; r++){
      quizData[r][0] = in.nextLine();
      
      for(int i = 0; i < numAnswers; i++){
        quizData[r][2 + i] = in.nextLine();
      }
    }
    
    if(in.hasNextLine()){
      limit = Integer.parseInt(in.nextLine());
    }
  }
  
  public void loadAnswers(String filename)
  {
  
    Scanner in = null;
    
    try{
      in = new Scanner(new File(filename));
    }catch(Exception e){}
    
    //Load Data for each Answer
    for(int r = 0; r < numQuestions; r++){
      quizData[r][1] = in.nextLine();
    }
  }
  
  public void loadUsers(String filename)
  { 
    
    Scanner in = null;
    
    try{
      in = new Scanner(new File(filename));
    }catch(Exception e){}
    
    //Load Each User
    while(in.hasNextLine()){
      userData[numUsers] = in.nextLine().split(" ");
      System.out.println("Loaded user: " + userData[numUsers][0]);
      numUsers++;
    }
    
    System.out.println();
  }
  
  ////////////////////////////////////////// ///////////////////////////////////////
  //Input
  ////////////////////////////////////////// ///////////////////////////////////////
  
  public void actionPerformed(ActionEvent e)
  {
    
    Object s = e.getSource();
    
    //Manage Users
    if(s.equals(newUser))
      createUser();
    else if(s.equals(login))
      startLogin();
    else if(s.equals(logout)){
      logout();
      
      start.setEnabled(false);
      turnin.setEnabled(false);
      logout.setEnabled(false);
      login.setEnabled(true);
      newUser.setEnabled(true);
    }
    
    //Answer Selection
    else if(s.equals(answerA))
      currentAnswer = "a";
    else if(s.equals(answerB))
      currentAnswer = "b";
    else if(s.equals(answerC))
      currentAnswer = "c";
    else if(s.equals(answerD))
      currentAnswer = "d";
    
    //Next Answer
    else if(s.equals(nextButton)){
      answers[currentQuestion] = currentAnswer;
      numQuestionsAnswered++;
      
      if(numQuestionsAnswered != limit && numQuestionsAnswered != numQuestions)
        nextQuestion();
        
      if(numQuestionsAnswered == limit || numQuestionsAnswered == numQuestions){
        nextButton.setEnabled(false);
        turnin.setEnabled(true);
      }
    }
    
    //Login
    else if(s.equals(okButton)){
      if(login()){
        
        login.setEnabled(false);
        logout.setEnabled(true);
        newUser.setEnabled(false);
        
        if(userData[currentUser][3].equals(Integer.toString(-1))){
          start.setEnabled(true);
        }
      }
      
    }else if(s.equals(cancelButton))
      loginFrame.dispose();
  }
  
  public void menuSelected(MenuEvent e)
  {
    
    Object s = e.getSource();
    
    //Start
    if(s.equals(start)){
      
      numQuestionsAnswered = 0;
      nextButton.setEnabled(true);
      nextQuestion();
      start.setEnabled(false);
    }
    
    //Turnin
    else if(s.equals(turnin)){
      turnInAnswers();
      
      nextButton.setEnabled(false);
      turnin.setEnabled(false);
    }
  }
  
  ////////////////////////////////////////// ///////////////////////////////////////
  //Operations
  ////////////////////////////////////////// ///////////////////////////////////////
  
  public void createUser()
  {
    
    //Get Name
    String tempUser = JOptionPane.showInputDialog(null, "Please enter a user name: ", 
                                                  " New User", JOptionPane.QUESTION_MESSAGE);
    if(tempUser==null)
      return;
     
    //Get Password
    String tempPassword = JOptionPane.showInputDialog(null, "Please enter a user password:  ", 
                                                      "New User", JOptionPane.QUESTION_MESSAGE);
    if(tempPassword==null)
      return;
    
    //Check for Missing Data
    if(tempUser.equals("") || tempPassword.equals("")){
      JOptionPane.showMessageDialog(null, "A Username or Password was not found.", 
                                    "Error", JOptionPane.ERROR_MESSAGE);
      return;
    }
    
    //Check for Repeats
    for(int i=0; i<numUsers;i++){
      
      if(userData[i][0].equals(tempUser)){
        JOptionPane.showMessageDialog(null, "The user name already exists in the database!", 
                                      "Error", JOptionPane.ERROR_MESSAGE);
        return;
      }
    }
    
    //Complete
    JOptionPane.showMessageDialog(null, "You have successfully created your account!", 
                                  "Complete", JOptionPane.INFORMATION_MESSAGE);
    
    //Generate Hash
    Random r = new Random();
    int randomInt = r.nextInt(10);
    int randomInt2 = r.nextInt(10);
    String n = Integer.toString(randomInt) + Integer.toString(randomInt2);
    String hash = generateHash(tempPassword, n);
    
    //Store Data
    userData[numUsers][0] = tempUser;
    userData[numUsers][1] = hash;
    userData[numUsers][2] = n;
    userData[numUsers][3] = Integer.toString(-1);
    numUsers++;
  }
  
  public String generateHash(String s, String n)
  {
 
    String pn = s + n;
    return Integer.toString(pn.hashCode());
  }
  
  public void startLogin()
  {
      
    //Textfields
    userTextField = new JTextField();
    passwordTextField = new JPasswordField();
      
    //Buttons
    okButton = new JButton("Ok");
    okButton.addActionListener(this);
    cancelButton = new JButton("Cancel");
    cancelButton.addActionListener(this);
      
    //Login Frame
    loginFrame= new JFrame();
    loginFrame.setSize(200,200);
    loginFrame.setLayout(new GridLayout(3,3));
    
    loginFrame.add(new JLabel("User"));
    loginFrame.add(userTextField);
    loginFrame.add(new JLabel("Password"));
    loginFrame.add(passwordTextField);
    loginFrame.add(okButton);
    loginFrame.add(cancelButton);
      
    loginFrame.setVisible(true);
  }
  
  public boolean login()
  {
    
    String userTemp = userTextField.getText();
    String passwordTemp = passwordTextField.getText();
    
    //Check for Match
    for(int i = 0; i < numUsers; i++){
      
      //Retrieve Hash
      String hash = generateHash(passwordTemp, userData[i][2]);
      
      if(userTemp.equals(userData[i][0]) && hash.equals(userData[i][1])){
        
        currentUser = i;
          
        //Set Answers to Default
        for(int r = 0; r < numQuestions; r++){
          answers[r] = "";
        }
          
        System.out.println(userData[currentUser][0] + " has logged in\n");
        JOptionPane.showMessageDialog(null, "You have Successfully logged in!", 
                                      "Welcome" ,JOptionPane.INFORMATION_MESSAGE);
        
        loginFrame.dispose();
        
        return true;
      }
    }
    
    //No Match
    JOptionPane.showMessageDialog(null, "Wrong user name or password.", 
                                  "Error", JOptionPane.ERROR_MESSAGE);
    
    return false;
  }
  
  public void logout()
  {
    
    System.out.println(userData[currentUser][0] + " has logged out\n");
    currentUser = -1;
    
    //Reset Labels
    questionA.setText("");
    questionB.setText("");
    questionC.setText("");
    questionD.setText("");
    
    JOptionPane.showMessageDialog(null, "You have successfully logged out!", 
                                  "Logout" , JOptionPane.INFORMATION_MESSAGE);
  }
  
  public void nextQuestion()
  {
    
    Random r = new Random();
    
    while(true){
      int currentInt = r.nextInt(numQuestions);
      
      //Check for New Question
      if(answers[currentInt].equals("")){
        currentQuestion = currentInt;
        beginQuestion(currentQuestion);
        return;
      }
    }
  }
  
  public void beginQuestion(int id)
  {
    
    //Display Question
    displayedQuestionLabel.setText("Question " + (numQuestionsAnswered+1) + "/" + limit + ": " 
                                     + quizData[id][0]);
    
    //Display Possible Answers
    questionA.setText(quizData[id][2]);
    questionB.setText(quizData[id][3]);
    questionC.setText(quizData[id][4]);
    questionD.setText(quizData[id][5]);
    
    //Set Default Answer
    currentAnswer = "a";
  }
  
  public void turnInAnswers()
  {
    
    int numCorrect = 0;
    int numAnswered = 0;
    
    //Collect Correct and Answered
    for(int i = 0; i < numQuestions; i++){
      if(!answers[i].equals("")){
        numAnswered++;
        
        if(answers[i].equals(quizData[i][1])){
          numCorrect++;
        }
      }
    }
      
    //Reset Labels
    displayedQuestionLabel.setText("");
    questionA.setText("");
    questionB.setText("");
    questionC.setText("");
    questionD.setText("");
     
    //Save Score
    userData[currentUser][3] = Integer.toString(numCorrect);
    System.out.println("Answers have been turned in.\n");
    
    //Display Score
    JOptionPane.showMessageDialog(null, "You answered " + numCorrect + " correct out of " + numAnswered, 
                                   "Finished!", JOptionPane.INFORMATION_MESSAGE);
  }

  ////////////////////////////////////////// ///////////////////////////////////////
  //Data Saving
  ////////////////////////////////////////// ///////////////////////////////////////
  
  public void windowClosing(WindowEvent e)
  {
   
     PrintWriter d = null;
     PrintWriter g = null;
     
     try{
       d = new PrintWriter("Data.txt");
       g = new PrintWriter("Grades.txt");
     }catch(Exception f){
       return;
     }
     
     //Save User Data
     for(int i = 0; i < numUsers; i++){
       
       d.println(userData[i][0] + " " + userData[i][1] + " " + userData[i][2] + " " + userData[i][3]);
       g.println(userData[i][0] + " " + userData[i][3]);
       System.out.println("Saved user: "  + userData[i][0]);
     }
     
     d.close();
     g.close();
  }
  
  //Empty Methods
  public void menuCanceled(MenuEvent e){}
  public void menuDeselected(MenuEvent e){}
  public void windowOpened(WindowEvent e){}
  public void windowClosed(WindowEvent e){}
  public void windowActivated(WindowEvent e){}
  public void windowDeactivated(WindowEvent e){}
  public void windowIconified(WindowEvent e){}
  public void windowDeiconified(WindowEvent e){}
}